<?php

namespace App\Services;



use App\Models\Funds;
use App\Models\Order;
use App\Models\FgTaxType;
use App\Models\FgWageSettings;
use App\Models\FgGameSettings;
use App\Models\FgAgentWageRecord;
use App\Models\OfflineAgentRelation;
use Illuminate\Support\Facades\Log;

class BrokerageService
{
    /*
     * 生成抽水期数
     */
    public static function createPeriod()
    {
        $time = time() - 1800;
        $h = date('H', $time);
        $i = date('i', $time);
        return date('Ymd') . $h . (($i > 30) ? '30' : '00') . $h . (($i > 30) ? '60' : '30');
    }

    /*
     * 生成一天所有的抽水周期
     */
    public static function createAllDayPeriod($timestamp)
    {
        $timestamp = $timestamp ? $timestamp : strtotime("-1 day");
        $date = date('Ymd', $timestamp);
        $periods = [];
        for ($i = 0; $i < 24; $i++) {
            $hour = ($i < 10) ? '0' . $i : $i;
            $periods[] = $date . $hour . '00' . $hour . '30';
            $periods[] = $date . $hour . '30' . $hour . '60';
        }
        return $periods;
    }

    /*
     * 生成总代抽水记录
     */
    public static function createBrokerage($period)
    {
        //获取各个游戏的税收比例
        $gameTaxRatios = FgTaxType::get()->toArray();
        $taxRatios = [];
        foreach ($gameTaxRatios as $v) {
            $taxRatios[$v['id']] = $v['ratio'];
        }
        unset($gameTaxRatios);

        //遍历各个等级代理
        for ($i = 0; $i < 18; $i++) {
            $model = FgWageSettings::select(['s.*', 'u.wallet_id', 'o.level','s.creator_id'])
                ->from('fg_wage_settings as s')
                ->leftJoin('user as u', 's.user_id=u.id')
                ->leftJoin('offline_agent_user as o', 's.user_id=o.user_id')
                ->andWhere(['=', 'o.level', $i]);
                //->andWhere(['=', 's.id', 1]) //测试代码
            $setting = $model->get()->toArray();
            Log::error("========setting list :" . json_encode([$setting, $model->createCommand()->getRawSql()]));
            foreach ($setting as $v) {
                //如果已经生成记录则跳过
                $r = FgAgentWageRecord::select(['id'])->andWhere(['=', 'period', $period])->andWhere(['=', 'user_id', $v['user_id']])->asArray()->one();
                if ($r) {
                    Log::error("========如果已经生成记录则跳过:" . json_encode([$r, $v]));
                    continue;
                }

                //获取上级抽水配置（获取抽水比例）
                $upperWageSetting = FgWageSettings::select(['ratio'])->where(['=','user_id', $v['creator_id']])->asArray()->one();
                Log::error("========获取上级抽水配置:" . json_encode([$upperWageSetting, $v]));
                //获取下级所有代理和会员
                $members = OfflineAgentRelation::where(['=', 'pid', $v['user_id']])->get()->toArray();
                $user_ids = [];
                foreach ($members as $member) {
                    $user_ids[] = $member['user_id'];
                }
                array_push($user_ids, $v['user_id']);
                //获取报表统计数据
                $state = static::statisticsOrder($period, $user_ids, $taxRatios, $v['ratio']);

                if ($state['team_wage'] > 0) {
                    //生成抽水记录
                    $data = [];
                    $data['FgAgentWageRecord']['period'] = $period;
                    $data['FgAgentWageRecord']['game_type'] = 'fg';
                    $data['FgAgentWageRecord']['creator_id'] = $v['creator_id'];
                    $data['FgAgentWageRecord']['creator_name'] = $v['creator_name'];
                    $data['FgAgentWageRecord']['user_id'] = $v['user_id'];
                    $data['FgAgentWageRecord']['user_name'] = $v['user_name'];
                    $data['FgAgentWageRecord']['level'] = $v['level'];
                    $data['FgAgentWageRecord']['total_amount'] = $state['total_amount'];
                    $data['FgAgentWageRecord']['amount1'] = $state['amount1'];
                    $data['FgAgentWageRecord']['amount2'] = $state['amount2'];
                    $data['FgAgentWageRecord']['amount3'] = $state['amount3'];
                    $data['FgAgentWageRecord']['tax_ratio1'] = $taxRatios[1];
                    $data['FgAgentWageRecord']['tax_ratio2'] = $taxRatios[2];
                    $data['FgAgentWageRecord']['tax_ratio3'] = $taxRatios[3];
                    $data['FgAgentWageRecord']['total_tax'] = $state['total_tax'];
                    $data['FgAgentWageRecord']['tax1'] = $state['tax1'];
                    $data['FgAgentWageRecord']['tax2'] = $state['tax2'];
                    $data['FgAgentWageRecord']['tax3'] = $state['tax3'];
                    $data['FgAgentWageRecord']['upper_wage_ratio'] = $upperWageSetting['ratio'] ?? 0;//上级抽水比例
                    $data['FgAgentWageRecord']['wage_ratio'] = $v['ratio'];//自身抽水比例
                    $data['FgAgentWageRecord']['team_wage'] = $state['team_wage'];
                    $data['FgAgentWageRecord']['operate_user_id'] = 0;
                    $data['FgAgentWageRecord']['operate_user_name'] = '系统';
                    $data['FgAgentWageRecord']['created'] = time();
                    $data['FgAgentWageRecord']['updated'] = time();

                    $model = new FgAgentWageRecord();
                    if (!$model->load($data) || !$model->save()) {
                        Log::info("============ create FgAgentWageRecord fail");
                    }
                }
            }
        }

        self::statisticsBrokerage($period);
    }

    /*
     * 获取报表统计数据
     */
    public static function statisticsOrder($period, $user_ids, $taxRatios, $wageRatio)
    {
        $startTime = date('Y-m-d H:i:s', strtotime(substr($period, 0, 12) . '00'));
        $endTime = date('Y-m-d H:i:s', strtotime(((substr($period, 0, 8) . substr($period, -4)) - 1) . '59'));

        //根据税收类型获取游戏ids
        $state = [
            'total_amount' => 0,
            'amount1' => 0,
            'amount2' => 0,
            'amount3' => 0,
            'total_tax' => 0,
            'tax1' => 0,
            'tax2' => 0,
            'tax3' => 0,
            'team_wage' => 0,
            'wage1' => 0,
            'wage2' => 0,
            'wage3' => 0,
        ];

        foreach ($taxRatios as $k => $v) {
            $game = FgGameSettings::select(['game_id'])->where(['=', 'tax_type', $k])->get()->toArray();
            $gameIds = array_column($game, 'game_id');

            if ($gameIds) {
                $data = Order::select([
                    "sum(`valid_money`) as valid_money",
                    "sum(abs(`win_loss`)) as win_loss",
                ])
                    ->andWhere(['>=', 'date', $startTime])
                    ->andWhere(['<=', 'date', $endTime])
                    ->andWhere(['=', 'type_name', 'FG'])
                    ->andWhere(['in', 'user_id', $user_ids])
                    ->andWhere(['in', 'game_id', $gameIds])
                    //->createCommand()->getRawSql();print_r($data);exit;
                    ->asArray()->one();
                //该注单游戏对应的税收比例( 1捕猎类 2对战类 3街机类)
                if ($k == 1) {
                    $state['amount' . $k] = $data['win_loss'] ?? 0;
                    $state['tax' . $k] = $data['win_loss'] * $v / 100;
                    $state['wage' . $k] = $data['win_loss'] * ($v / 100) * ($wageRatio / 100);
                } else if ($k == 2) {
                    $state['amount' . $k] = $data['valid_money'] ?? 0;
                    $state['tax' . $k] = $data['valid_money'] * ($v / 100) / 2;
                    $state['wage' . $k] = $data['valid_money'] * ($v / 100) / 2 * ($wageRatio / 100);
                } else if ($k == 3) {
                    $state['amount' . $k] = $data['valid_money'] ?? 0;
                    $state['tax' . $k] = $data['valid_money'] * ($v / 100);
                    $state['wage' . $k] = $data['valid_money'] * ($v / 100) * ($wageRatio / 100);
                }
                $state['total_amount'] += $state['amount' . $k];
                $state['total_tax'] += $state['tax' . $k];
                $state['team_wage'] += $state['wage' . $k];
            }
        }
        return $state;
    }

    /*
     * 统计该代理自己和下级代理所获得的抽水,并派发抽水
     */
    public static function statisticsBrokerage($period)
    {
        //获取所有未派发抽水的记录 统计下级抽水后计算出该代理的抽水
        $records = FgAgentWageRecord::select(['r.*', 'u.wallet_id'])
            ->from('fg_agent_wage_record as r')
            ->leftJoin('user as u', 'r.user_id=u.id')
            ->andWhere(['=', 'r.period', $period])
            ->andWhere(['=', 'r.status', 0])
            ->get()->toArray();
        foreach ($records as $v) {
            //统计该代理的直属下级代理的抽水
            $data = FgAgentWageRecord::select([
                "sum(`team_wage`) as team_wage",
            ])
                ->andWhere(['=', 'period', $period])
                ->andWhere(['=', 'creator_id', $v['user_id']])
                ->andWhere(['=', 'level', $v['level'] + 1])
                ->asArray()->one();
            $subAgentWage = $data['team_wage'] ?? 0;
            $wage = $v['team_wage'] - $subAgentWage;

            //更新改代理下级抽水和自己所得抽水
            $record = FgAgentWageRecord::where($v['id'])->first();
            $record->sub_agent_wage = $subAgentWage;
            $record->wage = $wage;
            $record->status = 1;
            $record->updated = time();
            if ($record->save()) {
                //派发抽水
                self::payoff($v, $wage);
            }
        }
    }

    /*
     * 派发抽水
     */
    private static function payoff($userInfo)
    {
        $t = DB::beginTransaction();
        try {
            if (isset($userInfo['creator_id']) && $userInfo['creator_id'] > 0) {
                //获取上级代理主钱包数据
                $d = Funds::find()
                    ->select(['f.*', 'u.wallet_id'])
                    ->from('funds as f')
                    ->leftJoin('user as u', 'f.id=u.wallet_id')
                    ->where(['=', 'u.id', $userInfo['creator_id']])
                    ->asArray()
                    ->one();
                if (($d['balance'] - $userInfo['team_wage']) >= 0) {
                    $funds = Funds::where((int)$d['wallet_id'])->first();
                    $funds->balance_before = $funds->balance;
                    $funds->balance -= $userInfo['team_wage'];
                    if ($funds->save()) {
                        $r = FundsDealLogService::createWagelog(
                            $userInfo['creator_id'],
                            $userInfo['creator_name'],
                            FundsDealLogService::generateDealNumber(),
                            -$userInfo['team_wage'],
                            $funds->balance,
                            '给下级派发抽水',
                            FundsDealLogService::TYPE_PAYOUT_WAGE,
                            FundsDealLogService::CATEGORY_COST
                        );
                        if (!$r) {
                            DB::rollBack();
                            return;
                        }
                    } else {
                        DB::rollBack();
                        return;
                    }
                } else {
                    $wageRecord = OfflineAgentWageRecord::where($userInfo['wallet_id'])->first();
                    if ($wageRecord) {
                        $wageRecord->status = 0;
                        $wageRecord->save();
                        DB::commit();
                    } else {
                        DB::rollBack();
                    }
                    return;
                }
            }
            //获取用户主钱包数据
            $funds = Funds::where((int)$userInfo['wallet_id'])->first();
            $funds->balance_before = $funds->balance;
            $funds->balance += $userInfo['team_wage'];
            if ($funds->save()) {
                $r = FundsDealLogService::createWagelog(
                    $userInfo['user_id'],
                    $userInfo['user_name'],
                    FundsDealLogService::generateDealNumber(),
                    $userInfo['team_wage'],
                    $funds->balance,
                    '抽水派发'
                );
                if ($r) {
                    DB::commit();
                } else {
                    DB::rollBack();
                }
                Log::info("insert Funds success");
            } else {
                DB::rollBack();
                Log::info("insert Funds fail");
            }
        } catch (Exception $e) {
            DB::rollBack();
        }
    }
}
